package NewContentManager;

##########################
#     OmnibusProxy       #
#    Krzysztof Ulman     #
# Politechnika Krakowska #
#      Kraków 2012       #
##########################

use strict;
use warnings;
use encoding 'utf8';

#use HTML::Element;
use HTML::TreeBuilder;
use ResultObject;
use URI;

#podstawowy adres wyszukiwarki - potrzebny do tworzenia adresow bezwzgledych
#my $baseUrl;

#drzewo zbudowane ze kodu HTML
#my $contentTree;

#adres URL do nastepnej strony z wynikami wyszukiwania
#my $nextPageUrl;

#lista wynikow wyszukiwania
#my @resultList;

#okreslenie parametrow kontenera na stronie
#my $tagName;
#my $tagAttributeName;
#my $tagAttributeValue;
#my $resultsBoxType;

our $BOX_TYPE_UL = 'ul';
our $BOX_TYPE_OTHER = 'other';

#konstruktor
sub new {
	shift;
	my $self = {};
	bless $self;
	
	my $baseUrl = shift;
	
	$self->{baseUrl} = $baseUrl;
	$self->{nextPageUrl} = '';
	$self->{resultPosition} = 0;
	
	return $self;
}

sub doWork {
	my $self = shift;
	
	#utworzenie drzewa HTML
	my $content = shift;
	my $contentTree	= HTML::TreeBuilder->new_from_content($content);
	$self->{contentTree} = $contentTree; 
	
	#wyszukanie informacji na stronie
	private_findResultListAndCompute($self);
	
	#usuniecie
	private_del($self);
}

#destruktor
sub private_del {
	my $self = shift;
	
	#usuniecie powiazan z drzewa HTML, aby GC mogl posprzatac
	my $contentTree = $self->{contentTree};
	$contentTree->delete();
}

sub private_findResultListAndCompute {
	my $self = shift;
	my $contentTree = $self->{contentTree};
	
	my $tagName = $self->{tagName};
	my $tagAttributeName = $self->{tagAttributeName};
	my $tagAttributeValue = $self->{tagAttributeValue};
	my $resultsBoxType = $self->{resultsBoxType};
	
	if($tagAttributeName ne 'id') {
		die('Atrubut o nazwie "' . $tagAttributeName . '" nie jest obslugiwany.');
	}
	
	#wyszukanie listy z wynikami
	my $found = 0;
	my @tagsList =  $contentTree->look_down(_tag => $tagName, id => $tagAttributeValue);
	if(scalar(@tagsList) == 1) {
		my $tag = $tagsList[0];
		private_findResult($self, $tag, $resultsBoxType);
		$found = 1;
	}
	
	if($found) {
		private_findNextPageUrl($self);
	} else {
		die('Nie znaleziono na stronie taga: ' . $tagName . '|' . $tagAttributeName . '|' . $tagAttributeValue);
	}
}

#wyszukuje kontener z wynikami
sub private_findResult {
	my $self = shift;
	my $tag = shift;
	my $resultsBoxType = shift;
	
	if($resultsBoxType eq $BOX_TYPE_UL) {
		#wyszukanie wszystkich list w podanym tagu
		my @uls = $tag->find_by_tag_name('ul', 'ol');
		
		if(scalar(@uls) > 1) {
			#mamy zagniezdzone listy, ktore trzeba pousuwac
			foreach my $ul (@uls) {
				#po kolei wszystkie dziecie
				my @descendants = $ul->descendants();
				foreach my $descendant (@descendants) {
					my @imgs = $descendant->find_by_tag_name('img');
					my $imgsNum = scalar(@imgs);
					if($imgsNum >= 3 && length(private_isNotEmptyResult($descendant)) < 100)  {
						#np. mamy <li>, w ktorym sa "Obrazy dla Warszawa"
						$descendant->delete();
					} else {
						#szukamy w nich list zagniezdzonych
						my @subUls = $descendant->find_by_tag_name('ul', 'ol');
						foreach my $subUl (@subUls) {
							#i usuwamy
							$subUl->delete();
						}						
					}
				}
			}
			#nastepnie na nowo wyszukujemy
			@uls = $tag->find_by_tag_name('ul', 'ol');
		}
		
		if(scalar(@uls) == 1) {
			private_findResult_ul($self, $uls[0]);
		} else {
			die('Nieprawidlowa liczba list: ' . scalar(@uls));
		}
	} elsif($resultsBoxType eq $BOX_TYPE_OTHER) {
		private_findResult_other($self, $tag);
	}
}

sub private_findResult_ul {
	my $self = shift;
	my $resultUl = shift;
	
	my @lis = $resultUl->find_by_tag_name('li');
	foreach my $li (@lis) {
		if(private_isNotEmptyResult($li)) {
			my @hrefs = $li->find_by_tag_name('a');
			if(scalar(@hrefs) > 0) {
				private_addResult($self, \@hrefs);
			}
		}
	}
}

#sprawdza, czy po usunieciu tekstow linkow i alt obrazkow pozostaje jakis tekst
#usuwa tez adresy www
sub private_isNotEmptyResult {
	my $li = shift;
	$li = $li->clone();
	my @tags = $li->find_by_tag_name('a', 'img');
	foreach my $tag (@tags) {
		$tag->delete();
	}
	my $liText = $li->as_text(skip_dels => 1);
	print "- " . $liText . "\n";
	$liText =~ s/(http:\/\/)?([a-z0-9-]+)?(\.[a-z0-9-]+)+\/?(.+?)?\s//gi;
	$liText =~ s/(http:\/\/)?([a-z0-9-]+)?(\.[a-z0-9-]+)+\/?(.+?)?$//gi; #rozni sie tylko ostatnim znakiem
	print "- " . $liText . "\n\n\n";
	return length($liText);
}

sub private_findResult_other {
	my $self = shift;
	my $resultBox = shift;
	
	my @h1s = $resultBox->find_by_tag_name('h1');
	foreach my $h1 (@h1s) {
		my @hrefs = $h1->find_by_tag_name('a');
		if(scalar(@hrefs) > 0) {
			private_addResult($self, \@hrefs);
		}
	}
}

#wyciaga dane, tworzy obiekt Result i dodaje do listy
sub private_addResult {
	my $self = shift;
	my $hrefsRef = shift;
	my @hrefs = @{$hrefsRef};
	
	#odczytanie listy lub stworzenie nowej
	my $resultListRef = $self->{resultList};
	my @resultList;
	if($resultListRef) {
		@resultList = @{$resultListRef};
	}
	
	#sprawdzamy po kolei wszystkie linki, czesc z nich moze byc np. obrazkami, takie pomijamy
	foreach my $href (@hrefs) {
		#odczytanie danych
		my $title = $href->as_text(skip_dels => 1);
		my $url = $href->attr('href');
		#przygotowanie obiektu
		if($title ne '' && $url ne '') {
			#odczytanie pozycji
			$self->{resultPosition}++;
			my $resultPosition = $self->{resultPosition};
			my $resultObject = ResultObject->new($title, $url, $resultPosition);
			push(@resultList, $resultObject);
			last; #koniec iterowania
		}
	}
	
	#zapisanie isty
	$self->{resultList}	= \@resultList;
}

#wyszukanie linku do kolejnej strony
sub private_findNextPageUrl {
	my $self = shift;
	my $contentTree = $self->{contentTree};
	
	#link do nastepnej strony
	my @hrefs = $contentTree->find_by_tag_name('a');
	if(scalar(@hrefs) > 0) {
		foreach my $href (@hrefs) {
			my $hrefText = $href->as_text(skip_dels => 1);
			if($hrefText =~ /^Następna/ || $hrefText =~ /^Next/) {
				my $nextPageUrl = $href->attr('href');
				$self->{nextPageUrl} = $nextPageUrl;
				last; #taki break;
			}
		}
	}
}

#zwraca adres do nastepnej strony
sub getNextPageUrl {
	my $self = shift;
	my $nextPageUrl = $self->{nextPageUrl};
	if($nextPageUrl ne '') {
		$nextPageUrl = private_getAbsoluteUrl($self, $nextPageUrl);
	}
	return $nextPageUrl;
}

#zamienia adres ew. adres wzgledny na bezwzgledny
sub private_getAbsoluteUrl {
	my $self = shift;
	my $nextPageUrl = shift;
	my $baseUrl = $self->{baseUrl};
	if($baseUrl) {
		return URI->new_abs($nextPageUrl, $baseUrl);
	} else {
		return $nextPageUrl;
	}
}

#zwraca liste wynikow wyszukiwania
sub getResultList {
	my $self = shift;
	return $self->{resultList};
}

#zwraca licze obiektow na liscie wynikowej
sub getResultsNumber {
	my $self = shift;
	my @resultList = $self->{resultList};
	my $number = @resultList;
	return $number;
}

#ustawia parametry kontenera
sub configureResultsBoxAttributes {
	my $self = shift;
	
	my $tagName = shift;
	my $tagAttributeName = shift;
	my $tagAttributeValue = shift;
	my $resultsBoxType = shift;
	
	$self->{tagName} = $tagName;
	$self->{tagAttributeName} = $tagAttributeName;
	$self->{tagAttributeValue} = $tagAttributeValue;
	$self->{resultsBoxType} = $resultsBoxType;
}

sub BOX_TYPE_UL {
	return $BOX_TYPE_UL;
}

sub BOX_TYPE_OTHER {
	return $BOX_TYPE_OTHER;
}

1;